const userModel = require("../../model/user");
const permissionModel = require("../../model/permissions");
const paging = require("../../utils/paging");
const mongoose = require("mongoose");
const Joi = require("joi");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const departmentModel = require("../../model/department");
const { flatToTree } = require("../../utils/treeHandle");
const { query } = require("express");

// 查询用户列表
exports.getUserList = async (req, res, next) => {
	try {
		const { getPaginatedResults, total } = await paging({
			req,
			model: userModel,
			filterCallback: (query) => {
				if (req.query.nickname) query.nickname = new RegExp(req.query.nickname);
			},
		});
		const ret = await getPaginatedResults().sort({ _id: -1 });

		res.json({ code: 200, msg: "查询用户列表成功", data: { data: ret, total } });
	} catch (error) {
		res.json({ code: 500, msg: "查询用户失败" });
		next({ msg: "查询用户失败", error });
	}
};
// 新增用户
exports.addUser = async (req, res, next) => {
	req.body.password = bcrypt.hashSync(req.body.password, 10);

	try {
		const ret = await userModel.create(req.body);
		res.json({ code: 200, msg: "新增用户成功", data: ret });
	} catch (error) {
		res.json({ code: 500, msg: "新增用户失败" });
		next({ msg: "新增用户失败", error });
	}
};
// 删除用户
exports.deleteUser = async (req, res, next) => {
	try {
		const ret = await userModel.deleteOne({ _id: req.body.id });
		res.json({ code: 200, msg: "删除用户成功", data: ret });
	} catch (error) {
		res.json({ code: 500, msg: "删除用户失败" });
		next({ msg: "删除用户失败", error });
	}
};
// 修改用户
exports.updateUser = async (req, res, next) => {
	if (req.body.password) req.body.password = bcrypt.hashSync(req.body.password, 10);

	try {
		const ret = await userModel.updateOne({ _id: req.body._id }, req.body);
		res.json({ code: 200, msg: "修改用户成功", data: ret });
	} catch (error) {
		res.json({ code: 500, msg: "修改用户失败" });
		next({ msg: "修改用户失败", error });
	}
};

// 获取用户的权限
exports.getUserPermissions = async (req, res, next) => {
	try {
		let ret = await userModel.aggregate([
			// 匹配用户
			{
				$match: { _id: req.userInfo._id },
			},
			// 关联查询身份表
			{
				$lookup: { from: "roles", localField: "role", foreignField: "_id", as: "role" },
			},
			// 关联查询权限表
			{
				$lookup: {
					from: "permissions",
					localField: "role.permissions",
					foreignField: "_id",
					as: "permissions",
				},
			},
			// 如果是超管, 则不进行展开, 如果它一展开, 就直接变成一个空数组了
			...(req.userInfo.isSuper ? [] : [{ $unwind: "$permissions" }, { $match: { "permissions.status": "enable" } }]),
			{
				$group: {
					_id: "$_id",
					role: { $first: "$role" },
					permissions: { $push: "$permissions" },
					isSuper: { $first: "$isSuper" },
				},
			},
		]);
		ret = ret[0];

		// 超级管理员
		if (req.userInfo.isSuper) ret.permissions = await permissionModel.find({ status: "enable" }).lean();
		// 清除无用信息
		ret.role.forEach((roleItem) => delete roleItem.permissions);

		// 总权限列表
		const allPermission = [];
		// 转换为树形结构
		const routerPermissions = flatToTree({
			dataArr: ret.permissions,
			forEachBeforeHandle: (item) => {
				allPermission.push(item.key);
				// 如果type不为[catalogue,menu], 则不添加到路由权限
				if (!["catalogue", "menu"].includes(item.type)) throw new Error("");
			},
		});

		delete ret.permissions;
		ret.routePermissions = routerPermissions;
		ret.allPersmissions = allPermission;

		res.json({ code: 200, msg: "查询用户详情成功", data: ret });
	} catch (error) {
		res.json({ code: 500, msg: "查询用户详情失败" });
		next({ msg: "查询用户详情失败", error });
	}
};
// 根据Token获取用户信息
exports.byTokenGetUserInfo = async (req, res, next) => {
	const userId = req.userInfo._id;
	try {
		const ret = await userModel.findById(userId).select("-role -department");
		res.json({ code: 200, msg: "获取信息成功", data: ret });
	} catch (error) {
		res.json({ code: 500, msg: "查询用户详情失败" });
		next({ msg: "查询用户详情失败", error });
	}
};

// 用户登录
exports.login = async (req, res, next) => {
	const { error } = Joi.object({
		username: Joi.string().required().min(3).max(30).messages({
			"string.min": "用户名长度不能小于3",
			"string.max": "用户名长度不能大于30",
			"any.required": "用户名不能为空",
			"string.base": "用户名必须为字符串类型",
		}),
		password: Joi.string().required().min(6).max(30).messages({
			"string.min": "密码长度不能小于6",
			"string.max": "密码长度不能大于30",
			"any.required": "密码不能为空",
			"string.base": "密码必须为字符串类型",
		}),
	})
		.unknown()
		.validate(req.body);
	if (error) return res.json({ code: 500, msg: error.message });

	try {
		// 检测数据库中是否有该用户
		const userInfo = await userModel.findOne({ username: req.body.username }).select("+password").lean();
		if (!userInfo) return res.json({ code: 500, msg: "用户名不存在" });
		// 检测密码是否正确
		const isMatch = bcrypt.compareSync(req.body.password, userInfo.password);
		if (!isMatch) return res.json({ code: 500, msg: "密码错误" });
		// 检测状态是否正常
		if (userInfo.status === "disable") return res.json({ code: 500, msg: "用户状态异常" });

		// 去除不必要的属性
		delete userInfo.role;
		delete userInfo.password;

		// 获取部门信息
		userInfo.department = await departmentModel.findById(userInfo.department).lean();
		if (userInfo.department.status === "disable") return res.json({ code: 500, msg: "部门状态异常" });

		// 下发token
		const token = jwt.sign({ id: userInfo._id, isSuper: userInfo.isSuper }, process.env.JWT_SECRET, { expiresIn: "24h" });
		res.json({ code: 200, msg: "登录成功", data: { token, ...userInfo } });
	} catch (error) {
		res.json({ code: 500, msg: "用户登录失败" });
		next({ msg: "用户登录失败", error });
	}
};
